/*
 * File:   vlakno.cpp
 * Author: Michal Zima
 *
 * Created on 17. kv�ten 2009, 18:58
 *
 * TVAR zadani - ID:priorita:Instrukce,Instrukce,Instrukce.....
 */
/* CHYBY */
/*
 * 1001 - ID neni cislo - SYNTAX ERROR
 * 1002 - chyby ":" za ID - SYNTAX ERROR
 * 1003 - Priorita neni cislo - SYNTAX ERROR
 * 1004 - Chybi ":" za prioritou - SYNTAX ERROR
 * 1005 - Chybna instrukce - pocatecni pismeno sedi - SYNTAX ERROR
 * 1006 - intrukce nebyla nalezena - SYNTAX ERROR
 * 1007 - Spatne zadani instrukce - cas neni cislo - SYNTAX ERROR
 *
 * 1103 - Priorita nema spravnou hodnotu - SYNTAX ERROR
 * 1101 - ID je duplicitni!! - SYNTAX ERROR
 *
 * 2001 - pri porovnavani instrukce doslo k chybe - FATAL ERROR!!
 * 2002 - polozka v pameti se zrtratila - FATAL ERROR!!
 *
 * 8001 - Nalezena instrukce s nulovou casovou delkou - zahozena
 * 8002 - Vlakno nenalezeno podle ID - create zahozeno
 *

 * 1103 - Priorita nema spravnou hodnotu
 * 1101 - ID je duplicitni!! // TODO udelat kontrolu duplicitnich ID
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>

/* Casova konstanta - nastaveno 100ms */
const int TIME_DEF = 100;

/*
 *       Deklarace struktur a proměnných
 */

typedef struct blok_instrukci
{
    int cislo_intrukce;
    int cas_instrukce;
    blok_instrukci* dalsi_instrukce;
};
typedef struct vzor_vlakno
{
    int ID_vlakna;
    int priorita_vlakna;
    blok_instrukci* instrukce_vlakna;
    vzor_vlakno* dalsi_vzor;
};
typedef struct vlakno
{
    int ID_unikat;
    int priorita_unikat;
    int delka_unikat;
    int ID_predek;
    blok_instrukci* aktualni_instrukce;
//    pthread_mutex_t mutex_unikat = PTHREAD_MUTEX_INITIALIZER;
};
typedef struct io_fronta
{
    io_fronta* dalsi_polozka;    
    int ID_polozky;
};
typedef struct cpu_fronta
{
    int ID_cpu;
    int priorita_cpu;
    cpu_fronta* dalsi_polozka;
};

vzor_vlakno* pamet = NULL; // ukazatel na zacatek seznamu moznych vlaken k vytvoreni
vzor_vlakno* aktualni_vzor = NULL; // ukazatel v seznamu moznych vlaken, aby se vedelo, kam zapsat dalsi
io_fronta* io_aktualne = NULL; // vrchol FIFO V/V jednotky
cpu_fronta* cpu_aktualne = NULL; // ukazatel naplanovaneho vlakna - round robin CPU

pthread_mutex_t io_mutex = PTHREAD_MUTEX_INITIALIZER;   // blokovani pristup k jednotky
pthread_mutex_t io_fronta_mutex = PTHREAD_MUTEX_INITIALIZER; // ochrana proti prepsani V/V FIFO

pthread_mutex_t cpu_mutex = PTHREAD_MUTEX_INITIALIZER; // blokovani pristup k CPU
pthread_mutex_t cpu_fronta_mutex = PTHREAD_MUTEX_INITIALIZER; // ochrana proti prepsani CPU prioritni fronty

pthread_mutex_t vypis = PTHREAD_MUTEX_INITIALIZER;  // synchronizace zapisu na vystup

/* polozky pro zapis udaju o moznem vlaknu */
int ID;                 // ID vlakna
int priorita;           // priorita vlakna
int cas;                // parametr instrukce (doba trvani nebo cislo vlakna)
int instrukce;          // cislo instrukce

int celkove_vzoru = 0;  // pocet radku s moznymi vlakny
int ID_global = 100;    // mozno vyuzit pro jine cislovani vlaken
int io_stav = 0;    // stav FIFO V/V jednotky
int bezicich_vlaken = 0; // pocet vytvorenych vlaken

//int* adresa;

int vytvoreno;          // 1 - pokud je vytvoren zaznam o vlaknu(pridava se do pameti) 0 - musi se vytvorit misto v pameti

char znak;              // pomocna promenna pro nacitani po znacich ze vstupu
int pomocna;              // pomocna promenna typu INT

/*
 *Deklarace funkci..
*/
int create_vlakno(int ID_vzor, int pred);   // vytvori novy thread podle vzoru a s informaci kdo ho vytvoril

void chyba(int cislo_chyby) // Vypise kod chyby a ukonci program, pokud je chyba zavazna
{
    printf("\n\nOou, neco se pokazilo :(, kod chyby = %d\n", cislo_chyby);
    if (cislo_chyby < 8000)
    {
        printf("Koncim program..\n\n\n");
        exit(1);
    }
}

void test_ID()
{
    int* ar = new int[celkove_vzoru];
    int citac = 0;
    vzor_vlakno* pomoc = pamet;
    while (pomoc != NULL)
    {
        ar[citac] = pomoc->ID_vlakna;
        citac++;
        pomoc = pomoc->dalsi_vzor;
    }
    for(int count = 0; count < celkove_vzoru; count++)
    {
        for(int count1 = 0; count1 < celkove_vzoru; count1++)
        {
            if ((count != count1) && (ar[count] == ar[count1]))
            {
                chyba(1101);
            }
        }
    }
}


void vytvor_zaznam() // vytvori novy mozny vzor
{
/*
    printf("Zapisuji informace o vlaknu a prvni instrukci do pameti...  \n");
    p[priorita-1]++;       // pridava se vlakno priority do pole p
    adresa = (int*) realloc(NULL, 5*sizeof(int));
    *adresa = ID;
    *(adresa + sizeof(int)) = priorita;
    *(adresa + 2*(sizeof(int))) = instrukce;
    *(adresa + 3*(sizeof(int))) = cas;
    *(adresa + 4*(sizeof(int))) = 0;
*/
    vzor_vlakno* novy_vzor;
    celkove_vzoru++;
    novy_vzor = new vzor_vlakno();
    if (pamet == NULL)
    {
        pamet = novy_vzor;
    }
    novy_vzor -> ID_vlakna = ID;
    novy_vzor -> priorita_vlakna = priorita;
    if (aktualni_vzor != NULL) {aktualni_vzor -> dalsi_vzor = novy_vzor;}
    blok_instrukci* prvni_instrukce = new blok_instrukci();
    prvni_instrukce -> cas_instrukce = cas;
    prvni_instrukce -> cislo_intrukce = instrukce;
    prvni_instrukce -> dalsi_instrukce = NULL;
    novy_vzor -> instrukce_vlakna = prvni_instrukce;
    aktualni_vzor = novy_vzor;
//    printf(" %d %d -- %d-%d",novy_vzor->ID_vlakna,novy_vzor->priorita_vlakna,prvni_instrukce->cislo_intrukce,prvni_instrukce->cas_instrukce);
// TODO ted zapsat adresu do pole priorit - predtim realokovat pole na velikost p(priorita)+1 (musi se zapsat nula na znameni konce!)

    //TODO pripravit zapis instrukci do pameti (malloc) - zapisuje se ID(int),priorita(int),instrukce(int),cas(int)
    // - nezapomenou na nulu na konci!!
}
void pridej_polozku() // prida instrukci k rozepsanemu vzoru
{
   /*
    int prvek = 0;
    int cislo = 6;
    int cykl = 0;

    while ((cislo != 0) || (prvek % 2 != 1))                //počítá kolik je prvků v instrukci
    {
        cislo = *(adresa + prvek*(sizeof(int)));
        prvek++;
        printf("Prvek: %d - cislo: %d\n",prvek,cislo);
    }

    prvek = prvek+2;

    for(cykl = 0;cykl<prvek-2;cykl++)
    {
        cislo = *(adresa + cykl*sizeof(int));
        printf(" %d",cislo);
    }
    printf(" --- puvodni\n");

    adresa = (int*) realloc(adresa, prvek*sizeof(int));

    for(cykl = 0;cykl<prvek;cykl++)
    {
        cislo = *(adresa + cykl*sizeof(int));
        printf(" %d",cislo);
    }
    printf(" --- zvetsena \n");

    *(adresa + (prvek-3)*sizeof(int)) = instrukce;
    *(adresa + (prvek-2)*sizeof(int)) = cas;
    *(adresa + (prvek-1)*sizeof(int)) = 0;

    for(cykl = 0;cykl<prvek;cykl++)
    {
        cislo = *(adresa + cykl*sizeof(int));
        printf(" %d",cislo);
    }
    printf(" --- pridana \n");
*/
    blok_instrukci* dalsi_ins = new blok_instrukci();
    dalsi_ins -> dalsi_instrukce = NULL;
    dalsi_ins -> cas_instrukce = cas;
    dalsi_ins -> cislo_intrukce = instrukce;
    blok_instrukci* b = aktualni_vzor->instrukce_vlakna;
    while(b->dalsi_instrukce != NULL)
    {
        b = b->dalsi_instrukce;
    }
    b->dalsi_instrukce = dalsi_ins;
//    printf(" %d-%d",dalsi_ins->cislo_intrukce,dalsi_ins->cas_instrukce);
}

void print()    // kontrolni vypis radku moznych vlaken
{
    vzor_vlakno* currRow = pamet;
    blok_instrukci* currInstr;
    while(currRow != NULL)
    {
        printf("radek=%d, priorita=%d", currRow->ID_vlakna, currRow->priorita_vlakna);
        currInstr = currRow->instrukce_vlakna;
        while(currInstr !=NULL)
        {
            printf(" %d-%d", currInstr->cislo_intrukce, currInstr->cas_instrukce);
            currInstr = currInstr->dalsi_instrukce;
        }
        printf("\n");
        currRow = currRow->dalsi_vzor;
    }
}
void print_cpu() // kontrolni vypis fronty na CPU
{
    cpu_fronta* pomoc = cpu_aktualne;
    pthread_mutex_lock(&vypis);
    printf("-------- zacatek fronty -----------\n");
    while(pomoc != NULL)
    {
    printf("ID: %d, priorita: %d, \n",pomoc->ID_cpu,pomoc->priorita_cpu);
    pomoc = pomoc -> dalsi_polozka;
    }
    printf("--------  konec fronty  -----------\n");
    pthread_mutex_unlock(&vypis);

}


int zapis_cas() // zapisuje nactena data do pameti po instrukci
{
//    printf("Nalezen cas po ktery se ma instrukce provadet - %d - %d \n", instrukce, cas);
    if (cas < 0){ return(-1);}
    if (vytvoreno == 0)
    {
        vytvor_zaznam();
        vytvoreno = 1;
    }
    else {pridej_polozku();}
    return(1);
}
void cpu() // nalezena instrukce CPU
{
    instrukce = 1;
}
void io() // nalezena instrukce IO
{
    instrukce = 2;
}
void sleep() // nalezena instrukce SLEEP
{
    instrukce = 3;
}
void create() // nalezena instrukce CREATE
{
    instrukce = 4;
}


void zaloz_vlakna() // najde nejnizsi ID a vytvori z nej vlakno
{
    printf("Zakladam prvni vlakno - ");
    vzor_vlakno* pomoc = pamet;
    int spust = pomoc->ID_vlakna;
    while(pomoc-> dalsi_vzor != NULL)
    {
        pomoc = pomoc->dalsi_vzor;
        if (pomoc->ID_vlakna < spust)
        {
            spust = pomoc->ID_vlakna;
        }
    }
    printf("vybrano vlakno %d \n", spust);
    create_vlakno(spust, (int) pthread_self());
}

void cpu_zapis_fronta(int prior) // zapise vlakno do fronty na procesor
{
    cpu_fronta* polozka = new cpu_fronta();
    polozka -> ID_cpu = (int) pthread_self();
    polozka-> priorita_cpu = prior;
    polozka->dalsi_polozka = NULL;

    pthread_mutex_lock (&cpu_fronta_mutex);
    if (cpu_aktualne == NULL)
    {
        cpu_aktualne = polozka;
    }
    else
    {
        cpu_fronta* pomoc = cpu_aktualne;
        if ((pomoc->dalsi_polozka != NULL) && (pomoc->priorita_cpu >= polozka->priorita_cpu))
        {
            while ((pomoc->dalsi_polozka != NULL) && (pomoc->dalsi_polozka->priorita_cpu >= polozka->priorita_cpu))
            {
                pomoc = pomoc->dalsi_polozka;
            }
            polozka->dalsi_polozka = pomoc->dalsi_polozka;
            pomoc->dalsi_polozka = polozka;
        }
        else
        {
            if (pomoc->priorita_cpu < polozka->priorita_cpu)
            {
                polozka -> dalsi_polozka = pomoc;
                cpu_aktualne = polozka;
            }
            else
            {
                pomoc -> dalsi_polozka = polozka;
            }
        }
    }
    pthread_mutex_unlock (&cpu_fronta_mutex);
}
void cpu_del_fronta() // vyhodi z fronty vlakno pro procesor
{
    pthread_mutex_lock(&cpu_fronta_mutex);

    cpu_fronta* pomoc_minuly = cpu_aktualne;
    cpu_fronta* pomoc = cpu_aktualne;

    while (pomoc->ID_cpu != (int) pthread_self())
    {
        pomoc_minuly = pomoc;
        pomoc = pomoc->dalsi_polozka;
        if (pomoc == NULL) {chyba(2003);}
    }

    if (pomoc_minuly->dalsi_polozka != NULL)
    {
        pomoc_minuly -> dalsi_polozka = pomoc ->dalsi_polozka;
        if (pomoc == cpu_aktualne)
        {
            cpu_aktualne = pomoc ->dalsi_polozka;
        }
        delete(pomoc);
    }
    else
    {
        delete(pomoc);
        cpu_aktualne = NULL;
    }
    pthread_mutex_unlock(&cpu_fronta_mutex);
}
void cpu_vlakno(int cyklu, int prior, int pred) // cyklus pro vypocet na CPU
{
    int hotovo = 0;
    while (hotovo != 1)
    {
        pthread_mutex_lock(&cpu_mutex);
        if (cpu_aktualne->ID_cpu == (int) pthread_self())
        {
            /*
            timespec* ts = new timespec();
            ts->tv_sec = 0;
            ts->tv_nsec = 1000000 * TIME_DEF;
            nanosleep(ts, ts);
            */
            usleep(1000*TIME_DEF);
            pthread_mutex_lock(&vypis);
//            printf("Vlakno %d [%d] udelalo cyklus (zbyva - %d).\n", pthread_self(), pred, cyklu-1);
            pthread_mutex_unlock(&vypis);
            cpu_del_fronta();
            if (cyklu == 1)
            {
                pthread_mutex_lock(&vypis);
                printf("Vlakno %d [%d] ukoncilo cpu.\n", pthread_self(), pred);
                pthread_mutex_unlock(&vypis);
            }
            else
            {
               cpu_zapis_fronta(prior);
            }
            hotovo = 1;
            pthread_mutex_unlock(&cpu_mutex);
        }
        else
        {
            pthread_mutex_unlock(&cpu_mutex);
        }
    }
}

void io_vlakno(int cyklu, int pred) // na IO udela zadany pocet cyklu
{
    int hotovo = 0;

    io_fronta* polozka = new io_fronta();
    polozka->ID_polozky = (int) pthread_self();
    polozka->dalsi_polozka = NULL;

    pthread_mutex_lock(&io_fronta_mutex);
    if (io_stav == 0)
    {
        io_aktualne = polozka;
        io_stav++;
    }
    else
    {
        io_fronta* pomoc = io_aktualne;
        while (pomoc->dalsi_polozka != NULL)
        {
            pomoc = pomoc->dalsi_polozka;
        }
        pomoc->dalsi_polozka = polozka;
        io_stav++;
    }
    pthread_mutex_unlock(&io_fronta_mutex);

    while (hotovo != 1)
    {
        pthread_mutex_lock(&io_mutex);
        if (io_aktualne->ID_polozky != (int) pthread_self())
        {
            pthread_mutex_unlock(&io_mutex);
            continue;
        }
        pthread_mutex_lock(&vypis);
        printf("Vlakno %d [%d] zahajuje V/V na dobu %d. \n", pthread_self(), pred, cyklu);
        pthread_mutex_unlock(&vypis);
/*
        timespec* ts = new timespec();
        ts->tv_sec = 0;
        ts->tv_nsec = 1000000 * TIME_DEF * cyklu;
        nanosleep(ts, ts);
*/
        usleep(1000*TIME_DEF*cyklu);

        pthread_mutex_lock(&io_fronta_mutex);
        io_stav--;
        io_fronta* del_pomoc = io_aktualne;
        io_aktualne = io_aktualne->dalsi_polozka;
        delete(del_pomoc);
        pthread_mutex_unlock(&io_fronta_mutex);
        pthread_mutex_lock(&vypis);
        printf("Vlakno %d [%d] ukocilo V/V. \n", pthread_self(), pred);
        pthread_mutex_unlock(&vypis);
        pthread_mutex_unlock(&io_mutex);
        hotovo = 1;
    }
}

void sleep_vlakno(int cyklu, int pred) // na zadany pocet cyklu uspi vlakno
{
    pthread_mutex_lock(&vypis);
    printf("Vlakno %d [%d] zahajuje sleep na dobu %d \n", pthread_self(), pred, cyklu);
    pthread_mutex_unlock(&vypis);
    /*
            timespec* ts = new timespec();
            ts->tv_sec = ((TIME_DEF*cyklu) / 1000);
            ts->tv_nsec = 1000000 * ((TIME_DEF * cyklu) % 1000);
            nanosleep(ts, ts);
     */
    usleep(1000*TIME_DEF*cyklu);
    pthread_mutex_lock(&vypis);
    printf("Vlakno %d [%d] ukoncilo sleep. \n", pthread_self(), pred);
    pthread_mutex_unlock(&vypis);
}

void* run(void* dta) // ridi vlakno, urcuje podle instrukce kam ma jit nebo zda je na konci a zavre ho
{
    vlakno* data = (vlakno*)dta;
    while(1)
    {
        for (int count = data->delka_unikat; count != 0; count--)
        {
            switch(data->aktualni_instrukce->cislo_intrukce)
            {
                    case 1:
                        if (data->delka_unikat == count)
                        {
                            cpu_zapis_fronta(data->priorita_unikat);
                            pthread_mutex_lock(&vypis);
                            printf("Vlakno %d [%d] zahajuje cpu na dobu %d \n", pthread_self(), data->ID_predek, data->delka_unikat);
                            pthread_mutex_unlock(&vypis);
                        }
                        cpu_vlakno(count, data->priorita_unikat, data->ID_predek);
                        break;
                    case 2:
                        io_vlakno(data->delka_unikat, data->ID_predek);
                        count = 1;
                        break;
                    case 3:
                        sleep_vlakno(data->delka_unikat, data->ID_predek);
                        count = 1;
                        break;
                    case 4:
                        create_vlakno(data->delka_unikat, data->ID_predek);
                        count = 1;
                        break;
                    default: chyba(2001);
            }
        }
        if (data->aktualni_instrukce->dalsi_instrukce == NULL)
        {
            pthread_mutex_lock(&vypis);
            printf("Vlakno %d [%d] dobehlo.\n", pthread_self(), data->ID_predek);
            pthread_mutex_unlock(&vypis);
            bezicich_vlaken--;
            pthread_exit(NULL);
        }
        data->aktualni_instrukce = data->aktualni_instrukce->dalsi_instrukce;
        data->delka_unikat = data->aktualni_instrukce->cas_instrukce;
    }
}

int create_vlakno(int ID_vzor, int pred)    // vytvori vlakno podle vzoru s informaci o predkovi
{
    pthread_t v;
    vzor_vlakno* test = pamet;
    while(test != NULL)
    {
        if (test->ID_vlakna == ID_vzor)
        {
            vlakno* vlakno_data = new vlakno();
            vlakno_data->ID_unikat = ID_global++;
            vlakno_data->aktualni_instrukce = test->instrukce_vlakna;
            vlakno_data->delka_unikat = test->instrukce_vlakna->cas_instrukce;
            vlakno_data->priorita_unikat = test->priorita_vlakna;
            vlakno_data->ID_predek = test->ID_vlakna;
            pthread_create(&v, NULL, run, (void*) vlakno_data);
            pthread_mutex_lock(&vypis);
            printf("Vlakno %d [%d] vytvorilo novy thread %d [%d].\n", pthread_self(), pred, v, ID_vzor);
            pthread_mutex_unlock(&vypis);
            bezicich_vlaken++;
            return(0);
        }
        else
        {
            test = test->dalsi_vzor;        
        }
    }
    chyba(8002);
    return(-1);
}


void nacti_vstup() // nacita vstup ze standardniho vystupu...
{

    while (!feof(stdin)) // probíhá načítání ze vstupu, dokud se nedojde na konec souboru - Ctrl+D
    {
        vytvoreno = 0;
        pomocna = scanf("%d", &ID);          // nacteni ID - prvni udaj v radku - musi byt cislo
        if (pomocna != 1)
        {
            scanf("%c", &znak);
            if ((znak == '\n' || (!feof(stdin) || (znak == 13)) )){continue;}
            chyba(1001);
        }   // vypise chybu, pokud neni na zacatku cislo

//        printf("Nacteno ID - %d\n", ID);

        scanf("%c", &znak);                // kontroluje, jestli je zde dvojtecka
        if (znak != ':') { chyba(1002); }  // pokud neni dvojtecka, hodi chybu

        pomocna = scanf("%d", &priorita);    // kontroluje, zda je priotrita cislo
        if (pomocna != 1) { chyba(1003); }   // hodi chybu, kdyz neni priorita cislo
        if ((priorita < 1) || (priorita > 10)) { chyba(1103); } // Kontrola priority, jestli je v rozahu

//        printf("Nactena priorita - %d\n", priorita);

        scanf("%c", &znak);
        if (znak != ':') { chyba(1004); }
// Prohledava se seznam instrukci - az do konce radku
        while ((znak != '\n') && (!feof(stdin)) && (znak != 13))
        {
            scanf("%c", &znak);
// --------------- Roztrideni podle prvnich znaku na CPU IO SLEEP CREATE -----------------------------
            while ((znak != '-') && (znak != ' '))
            {
                if ((znak != 's') && (znak != 'c') && (znak != 'i')) {(chyba(1006));}
                if (znak == 'c')
                {
                    scanf("%c", &znak);
                    if (znak == 'p')
                    {
                       scanf("%c", &znak);
                       if (znak == 'u')
                       {
                           cpu();
                       }
                       else {(chyba(1005));}
                    }
                    else
                    {
                        if (znak == 'r' )
                        {
                            scanf("%c", &znak);
                            if (znak == 'e' )
                            {
                                scanf("%c", &znak);
                                if (znak == 'a' )
                                {
                                    scanf("%c", &znak);
                                    if (znak == 't' )
                                    {
                                        scanf("%c", &znak);
                                        if (znak == 'e' )
                                        {
                                            create();
                                        }
                                        else {(chyba(1005));}
                                    }
                                    else {(chyba(1005));}
                                }
                                else {(chyba(1005));}
                            }
                            else {(chyba(1005));}
                        }
                        else {chyba(1005);}
                    }
                }
                if (znak == 'i')
                {
                    scanf("%c", &znak);
                    if (znak == 'o')
                    {
                        io();
                    }
                    else {(chyba(1005));}
                }
                if (znak == 's')
                {
                    scanf("%c", &znak);
                    if (znak == 'l')
                    {
                        scanf("%c", &znak);
                        if (znak == 'e')
                        {
                            scanf("%c", &znak);
                            if (znak == 'e')
                            {
                                scanf("%c", &znak);
                                if (znak == 'p')
                                {
                                    sleep();
                                }
                                else {(chyba(1005));}
                            }
                            else {(chyba(1005));}
                        }
                        else {(chyba(1005));}
                    }
                    else {(chyba(1005));}
                }
                scanf("%c", &znak);
            }
//            printf("Rozpoznana instrukce, jdu na casove kvantum/cislo vlakna - %d\n", instrukce);
// +++++++++++++++ Roztrideni podle prvnich znaku na CPU IO SLEEP CREATE +++++++++++++++++++++++++++++
            cas = 0;
            while ((znak != '\n') && (znak != ',') && (!feof(stdin)) && (znak != 13))
            {
                scanf("%c", &znak);
                if ((znak > 57) || (znak < 48))
                {
                    if ((znak != '\n') && (!feof(stdin)) && (znak != ',') && (znak != 13))
                    {
//                      printf("\n\nznak - '%c' char = %d\n",znak,znak);
                        chyba(1007);
                    }
                }
                if ((znak != '\n') && (!feof(stdin)) && (znak != ',') && (znak != 13))
                {
                    cas = 10*cas + (znak-48);
                }
            }
            if (zapis_cas() == -1) {chyba(8001);};
        }
    }
}

int main(int argc, char** argv)
{
    pamet = NULL;
    printf("Vitej v programu vlakna - semestralni prace z OSY, vytvoril Michal Zima \n\n\n");
    printf("Zadej potrebne parametry vlaken ve tvaru - ID:Priorita:Instrukce1,Instrukce2,Instrukce3,... \n");
    nacti_vstup(); // postupne nacitani vsech radku vlaken
    printf("Hotovo - nacteno vporadku!!\n");
//  print();
    test_ID();
    zaloz_vlakna();
    while(bezicich_vlaken > 0)
    {
        usleep(1000*TIME_DEF); // kontrola po hodinovem cyklu, zda uz vlakna ukoncily cinnost
    }

    return (EXIT_SUCCESS);
}

